﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.IO.Ports;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace lononUART
{
    public partial class Form1 : Form
    {
        SerialPort sp = new SerialPort();
        public Displaydelegate disp_delegate;
        public delegate void Displaydelegate(byte[] InputBuf, int length);
        private bool Listening = false;//是否没有执行完invoke相关操作

        long backup_time = 0;
        /*
         *  获取空间坐标尺寸参数
         *  用于适应窗口拉伸
         */
        int win_width, win_height;
        int box_width, box_height;
        int box_send_width;
        int chack_box_1, chack_box_2;
        int but_3, but_4;
        int com_fig = 0;
        int trackBar1_value = 100;

        public Form1()
        {
            InitializeComponent();

            Size newSize = new Size(816, 489);
            this.MinimumSize = this.MinimumSize = newSize;
            this.Size = newSize;

            win_width = this.Width;
            win_height = this.Height;

            box_width = textBox1.Width;
            box_height = textBox1.Height;

            box_send_width = textBox2.Width;

            chack_box_1 = checkBox1.Location.X;
            chack_box_2 = checkBox2.Location.X;
            but_3 = button3.Location.X;
            but_4 = button4.Location.X;

            this.Resize += new System.EventHandler(this.Form_Resize);

            Assembly asm = Assembly.GetExecutingAssembly();
            Stream imgStream = asm.GetManifestResourceStream("lononUART.image.lononBle.png");
            pictureBox1.Image = Image.FromStream(imgStream);

            pictureBox1.SendToBack();

            comboBox2.DropDownStyle = ComboBoxStyle.DropDownList;

            disp_delegate = new Displaydelegate(DispUI);
            sp.DataReceived += new SerialDataReceivedEventHandler(Comm_DataReceived);

            for (int i = 1; i <= 30; i++)
            {
                string ComName = "COM" + i.ToString();
                try
                {
                    sp.PortName = ComName;
                    if (!sp.IsOpen)
                    {
                        sp.Open();
                        while (Listening) Application.DoEvents();
                        sp.Close();
                    }

                    comboBox1.Items.Add("COM" + i.ToString());
                    com_fig = 1;
                }
                catch
                {
                    continue;
                }
            }

            if(com_fig != 0)
                comboBox1.SelectedIndex = 0;

            comboBox2.Items.Add("9600");
            comboBox2.Items.Add("14400");
            comboBox2.Items.Add("19200");
            comboBox2.Items.Add("28800");
            comboBox2.Items.Add("38400");
            comboBox2.Items.Add("57600");
            comboBox2.Items.Add("115200");
            comboBox2.SelectedIndex = 0;

            label6.Text = "标签间隔：" + trackBar1_value + "ms";
        }

        private void Form_Resize(object sender, System.EventArgs e)
        {
            textBox1.Width = box_width - (win_width - this.Width);
            textBox1.Height = box_height - (win_height - this.Height);

            textBox2.Width = box_send_width - (win_width - this.Width);

            checkBox1.Left = chack_box_1 - (win_width - this.Width);
            checkBox2.Left = chack_box_2 - (win_width - this.Width);

            button3.Left = but_3 - (win_width - this.Width);
            button4.Left = but_4 - (win_width - this.Width);
        }

        private void button1_Click(object sender, EventArgs e)
        {
            if(com_fig != 1)
            {
                MessageBox.Show("没有有效COM");
                return;
            }

            if (sp.IsOpen)
            {
                try
                {
                    while (Listening) Application.DoEvents();
                    sp.Close();
                    button1.Text = "打开";
                    return;
                }
                catch (Exception ex)
                {
                    MessageBox.Show("错误：" + ex.Message, "C#串口通信");

                    button1.Text = "打开";
                    com_fig = 0;
                    up_com();
                    return;
                }
            }

            sp.PortName = comboBox1.Text;
            sp.BaudRate = int.Parse(comboBox2.Text); ;
            sp.DataBits = 8;
            sp.StopBits = (StopBits)1;
            
            try
            {
                if (sp.IsOpen)
                {
                    while (Listening) Application.DoEvents();
                    sp.Close();
                    sp.Open();
                }
                else
                {
                    sp.Open();

                    sp.RtsEnable = checkBox_RTS.Checked;
                    sp.DtrEnable = checkBox_DTR.Checked;
                }
                button1.Text = "关闭";
            }
            catch (Exception ex)
            {
                MessageBox.Show("错误：" + ex.Message, "C#串口通信");

                button1.Text = "打开";
                com_fig = 0;
                up_com();
                return;
            }
        }

        void Comm_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            Byte[] InputBuf = new Byte[1024 * 32];
            int len = sp.BytesToRead;

            try
            {
                Listening = true;//设置标记，说明我已经开始处理数据，一会儿要使用系统UI的。
                sp.Read(InputBuf, 0, len);
                System.Threading.Thread.Sleep(50);
                this.Invoke(disp_delegate, InputBuf, len);
            }
            catch (TimeoutException ex)
            {
                MessageBox.Show(ex.ToString());
            }
            Listening = false;//我用完了，ui可以关闭串口了。
        }

        private static string byteToHexStr(byte[] bytes, int length)
        {
            string returnStr = "";
            if (bytes != null)
            {
                for (int i = 0; i < length; i++)
                {
                    returnStr += bytes[i].ToString("X2") + " ";
                }
            }
            return returnStr;
        }

        public void DispUI(byte[] InputBuf,int lenght)
        {
            ASCIIEncoding encoding = new ASCIIEncoding();


            //ascii
            if (checkBox3.Checked)
            {
                long now_ms = (DateTime.Now.ToUniversalTime().Ticks - 621355968000000000) / 10000;
                long sec_ms = now_ms % 1000;
                string ms_ = sec_ms.ToString().PadLeft(3, '0');

                if (now_ms > (backup_time + trackBar1_value))
                {
                    if (textBox1.Text == "")
                        textBox1.Text = textBox1.Text + "[" + DateTime.Now.ToLongTimeString() + " " + ms_ + "] ";
                    else
                        textBox1.Text = textBox1.Text + "\r\n[" + DateTime.Now.ToLongTimeString() + " " + ms_ + "] ";
                }
                if (checkBox1.Checked)
                    textBox1.Text = textBox1.Text + byteToHexStr(InputBuf, lenght);
                else
                    textBox1.Text = textBox1.Text + Encoding.UTF8.GetString(InputBuf); // encoding.GetString(InputBuf);

                backup_time = now_ms;
            }
            else
            {
                if (checkBox1.Checked)
                    textBox1.Text = textBox1.Text + byteToHexStr(InputBuf, lenght);
                else
                    textBox1.Text = textBox1.Text + Encoding.UTF8.GetString(InputBuf); //encoding.GetString(InputBuf);
            }

            textBox1.SelectionStart = textBox1.Text.Length;
            textBox1.ScrollToCaret();
        }

        public static byte[] GetByteArray(string shex)
        {
            string[] ssArray = shex.Split(' ');
            List<byte> bytList = new List<byte>();
            foreach (var s in ssArray)
            {               
                bytList.Add(Convert.ToByte(s, 16));
            }
            return bytList.ToArray();
        }

        public void up_com()
        {
            comboBox1.Items.Clear();

            while (Listening) Application.DoEvents();
            sp.Close();
            button1.Text = "打开";

            comboBox1.Text = "";

            com_fig = 0;
            for (int i = 1; i <= 30; i++)
            {
                string ComName = "COM" + i.ToString();
                try
                {
                    sp.PortName = ComName;
                    if (!sp.IsOpen)
                    {
                        sp.Open();
                        while (Listening) Application.DoEvents();
                        sp.Close();
                    }

                    comboBox1.Items.Add("COM" + i.ToString());
                    com_fig = 1;
                }
                catch
                {
                    continue;
                }
            }

            if (com_fig != 0)
                comboBox1.SelectedIndex = 0;
        }

        private void button5_Click(object sender, EventArgs e)
        {
            up_com();
            comboBox1.DroppedDown = true;
        }

        private void textBox1_TextChanged(object sender, EventArgs e)
        {

        }

        private void ref_com_hover(object sender, EventArgs e)
        {
            
        }

        private void comboBox2_SelectedIndexChanged(object sender, EventArgs e)
        {
            
        }

        private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            
        }

        private void comboBox2_Click(object sender, EventArgs e)
        {
            if (sp.IsOpen)
                up_com();
        }

        private void comboBox1_Click(object sender, EventArgs e)
        {
            if (sp.IsOpen)
                up_com();
        }

        private void trackBar1_Scroll(object sender, EventArgs e)
        {
            trackBar1_value = trackBar1.Value;
            label6.Text = "标签间隔：" + trackBar1_value + "ms";
        }

        private void checkBox_RTS_CheckedChanged(object sender, EventArgs e)
        {
            if (sp.IsOpen)
            {
                sp.RtsEnable = checkBox_RTS.Checked;
                Console.WriteLine("RTS信号：" + sp.RtsEnable);
            }
        }

        private void checkBox_DTR_CheckedChanged(object sender, EventArgs e)
        {
            if (sp.IsOpen)
            {
                sp.DtrEnable = checkBox_DTR.Checked;
                Console.WriteLine("DTR信号：" + sp.DtrEnable);
            }
        }

        private void button2_Click(object sender, EventArgs e)
        {
            if (sp.IsOpen)
            {
                try
                {
                    if(checkBox2.Checked)
                    {
                        byte[] a = GetByteArray(textBox2.Text);

                        sp.Write(a,0,a.Length);
                    }
                    else
                    {
                        sp.Encoding = System.Text.Encoding.GetEncoding("utf-8");
                        sp.Write(textBox2.Text);
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show("错误：" + ex.Message);
                }
            }
            else
            {
                MessageBox.Show("请先打开串口！");
            }
        }

        private void button3_Click(object sender, EventArgs e)
        {
            textBox1.Text = "";
        }

        private void button4_Click(object sender, EventArgs e)
        {
            textBox2.Text = "";
        }

        private void pictureBox1_Click(object sender, EventArgs e)
        {

        }
    }
}
